Here I conduct a short story of different speeches of different U.S. presidents and nominees based on the data scraped from http://www.presidency.ucsb.edu/. For this project, speeches includes all inaugural addresses of past presidents, nomination speeches of major party candidates, farewell addresses and several public speeches from Donald Trump. The following textual analysises will be based on these speeches and I will have a especial focus on speeches of the current president Donald Trump.

Part1 Topic Modeling

Let’s firstly have a preview of what topics may be included in speeches concerning politics and presidential election. Let’s assume there are 6 topics in the speeches. Then we run LDA over our data and visualize the top-12-most-frequent words in each topic:

From the above graph, we can surely see some patterns. For instance, some words occur frequently in every topic, like “american”, “work”, “freedom” etc., which makes sense because a political speech is all about contents like them. On the other hand, we can see some diversities among topics. Like, topic1 focuses more on “law” while topic2 pays more attention on “peace and security”. So I manually set topic names to each of the topic: “Legislation”, “HomelandSecurity”, “Election”, “America”, “Reform” and “Work”.

Based on the divided topics, we can clearly find some hit words in political speeches. So now we want to find out how the frequencies of some of hit words change over time.

As we can see, they display different patterns although they are all hit topics. For example, the frequencies of “law” and “consititution” seems to be lower than before, which makes sense because laws are more complete than before. “immigration” and “work” occur more often now which also fits the trend. While “economy” and “trade” occur steadily during the course of development.

analysis ## explanation followed by online book frequency prob etc..

Also, we can cluster different inauguration speeches in terms of their topic:

From the figure, we can see that topics of inauguration speeches do have great diversity in terms of different presidents. For example, Donald Trump and John adams, which come from different clusters with far distance. It makes sense because back when John was president, he talked more about the independence of America. But now, topics concerning how to develop the country are mostly mentioned.

Part2 Analyzing Words

Now let’s do some analysis on the number of words in one sentence. First, let’s focus on all the inauguration speeches in each of different parties:

The message is clear that for “Fedralist”, “Whig”, “Democratic-Republican Party”, there are basically no preferences on using short or long sentences. However, for “Democratic” and “Republican”, they seem to prefer using more short words per sentence. Take Donald Trump for instance, the patterns in his different speeches are especially obvious:

We can see that his inauguration speeches seem normal, while his nominee speeches get to show some tend to use short words. What’s more, his public speeches show a apparent preference on using short words. And the length of each of the three types of speeches seems to increase, which may suggest he might sort of control himself at more formal venues. And let’s take a look at what exactly short sentences he said at different types of speeches.

nominee speeches:

inauguration speeches:

public speeches:

We can see that, at nominee and inauguration speeches, the short sentences do not convey much real information, like “thank you”. While in public speeches, short sentences do mean something. It may express his emotion, comments etc.

Based on the above analysis, since short words are some kind of hit in speeches. Now let’s take an especial look on the present president Donald Trump and focus on the frequency of word gruops (bigram). Because unlike single word, this may actually mean something like some specific topics.

First, let’s visualize what bigrams he said frequently in his different speeches:

Through visualizing that, analyzing bigram is helpful for exploratory analyses of the text. For example, if we want to know what word is ahead of “american” most:

We can see it’s Africa American, which is exactly one of his focus in the speeches.

Or, if we are wondering what kinks of policy he mentioned most:

The results also fit the real trend, which are immigration and foreign policies.

One step further, if we want to know what is his attitude or how he describe immigration, we can check the words that are ahead of “immigration”:

The reuslts have no surprise, because he has an extreme attitude about immigration. So no wonder he always emphasized “illegal” when talking about it.

Part3 Sentiment Analysis

Finally, we will implement sentiment analysis on the inauguration speeches and also have an especial look at Donald Trumps emotioms in his different speeches.

I will use “NRC” lexicon to do sentiment analysis. To do that, I quantify the positivity and negtivity of each word by calculating a score for each of them. The following figure shows the positivity of all the inauguration speeches:

From the figure, we can visualize that Zachary Tylor has the highest value of positivity, which may suggest that he was a good speecher and had a great way to persuade people. On the other hand, Warren Harding seems to have the lowest value of positivity. Anyway, the bright side is that none of the past presidents ends up with a negative value, which implies that inauguration speeches are some sort of good way to convey postive attitute and to provide hope and faith.

Now let’s look at the different speeches of Donald Trump. We also visaulize score of speeches in terms of types.

The patterns in the graph are obvious. We can see that Donald Trump has the highest score value in his inauguration speeches. While in nominee and public speeches, the scores are much lower, which may suggest that he is a “outright” guy who would not control his word even in public.

sentiment by sentence

Now we go one step further to analyze his speeches. This time we will analyze his sentiments by sentence. We will calculte the score of each sentence. Also, we will see what exactly are the most positive (negative) sentences he said. And we will compare them with those occur in another nominee’s speeches, Hillary Clinton.

Donald Trump’s most positive sentences:

Donald Trump’s most negtive sentences:

Hillary Clinton’s most positive sentences:

Hillary Clinton’s most negative sentences:

From the above analysis, we can see some interesting patterns. Based on some of the most positive and negative sentences, we can see that Donald Trump is an “outright” or even “extreme” nominee. We can see that some of his bad words directly aim at someone or something. He kind of cannot control himself saying them. On the other hand, for another nomiee in this year, Hillary Clinton, even her top negative words are more of like stating some facts rather than explicitly aiming at someone.

LS0tCnRpdGxlOiAiVGV4dCBNaW5pbmcgb24gUHJlc2lkZW50aWFsIFNwZWVjaGVzIgphdXRob3I6ICJaaWp1biBOaWUgOyB6bjIxNDYiCmRhdGU6ICJKYW51YXJ5IDMxLCAyMDE3IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT0gRkFMU0V9CnNvdXJjZSgiLi4vbGliL2xpYnJhcnkuUiIpCnNvdXJjZSgiLi4vbGliL3RleHQtcHJlcC5SIikKc291cmNlKCIuLi9saWIvc3BlZWNoRnVuY3MuUiIpCmBgYAoKCioqSGVyZSBJIGNvbmR1Y3QgYSBzaG9ydCBzdG9yeSBvZiBkaWZmZXJlbnQgc3BlZWNoZXMgb2YgZGlmZmVyZW50IFUuUy4gcHJlc2lkZW50cyBhbmQgbm9taW5lZXMgYmFzZWQgb24gdGhlIGRhdGEgc2NyYXBlZCBmcm9tIDxodHRwOi8vd3d3LnByZXNpZGVuY3kudWNzYi5lZHUvPi4gRm9yIHRoaXMgcHJvamVjdCwgc3BlZWNoZXMgaW5jbHVkZXMgYWxsIGluYXVndXJhbCBhZGRyZXNzZXMgb2YgcGFzdCBwcmVzaWRlbnRzLCBub21pbmF0aW9uIHNwZWVjaGVzIG9mIG1ham9yIHBhcnR5IGNhbmRpZGF0ZXMsIGZhcmV3ZWxsIGFkZHJlc3NlcyBhbmQgc2V2ZXJhbCBwdWJsaWMgc3BlZWNoZXMgZnJvbSBEb25hbGQgVHJ1bXAuIFRoZSBmb2xsb3dpbmcgdGV4dHVhbCBhbmFseXNpc2VzIHdpbGwgYmUgYmFzZWQgb24gdGhlc2Ugc3BlZWNoZXMgYW5kIEkgd2lsbCBoYXZlIGEgZXNwZWNpYWwgZm9jdXMgb24gc3BlZWNoZXMgb2YgdGhlIGN1cnJlbnQgcHJlc2lkZW50IERvbmFsZCBUcnVtcC4qKgoKIyMgUGFydDEgVG9waWMgTW9kZWxpbmcKCkxldCdzIGZpcnN0bHkgaGF2ZSBhIHByZXZpZXcgb2Ygd2hhdCB0b3BpY3MgbWF5IGJlIGluY2x1ZGVkIGluIHNwZWVjaGVzIGNvbmNlcm5pbmcgcG9saXRpY3MgYW5kIHByZXNpZGVudGlhbCBlbGVjdGlvbi4gTGV0J3MgYXNzdW1lIHRoZXJlIGFyZSA2IHRvcGljcyBpbiB0aGUgc3BlZWNoZXMuIFRoZW4gd2UgcnVuIExEQSBvdmVyIG91ciBkYXRhIGFuZCB2aXN1YWxpemUgdGhlIHRvcC0xMi1tb3N0LWZyZXF1ZW50IHdvcmRzIGluIGVhY2ggdG9waWM6CgpgYGB7cixpbmNsdWRlPUZBTFNFfQpjb3JwdXMubGlzdD1zZW50ZW5jZS5saXN0WzI6KG5yb3coc2VudGVuY2UubGlzdCktMSksIF0Kc2VudGVuY2UucHJlPXNlbnRlbmNlLmxpc3Qkc2VudGVuY2VzWzE6KG5yb3coc2VudGVuY2UubGlzdCktMildCnNlbnRlbmNlLnBvc3Q9c2VudGVuY2UubGlzdCRzZW50ZW5jZXNbMzoobnJvdyhzZW50ZW5jZS5saXN0KS0xKV0KY29ycHVzLmxpc3Qkc25pcGV0cz1wYXN0ZShzZW50ZW5jZS5wcmUsIGNvcnB1cy5saXN0JHNlbnRlbmNlcywgc2VudGVuY2UucG9zdCwgc2VwPSIgIikKcm0ucm93cz0oMTpucm93KGNvcnB1cy5saXN0KSlbY29ycHVzLmxpc3Qkc2VudC5pZD09MV0Kcm0ucm93cz1jKHJtLnJvd3MsIHJtLnJvd3MtMSkKY29ycHVzLmxpc3Q9Y29ycHVzLmxpc3RbLXJtLnJvd3MsIF0KCmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShjb3JwdXMubGlzdCRzbmlwZXRzKSkKCiNyZW1vdmUgcG90ZW50aWFsbHkgcHJvYmxlbWF0aWMgc3ltYm9scwpkb2NzIDwtdG1fbWFwKGRvY3MsY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKI3JlbW92ZSBwdW5jdHVhdGlvbgpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVQdW5jdHVhdGlvbikKI1N0cmlwIGRpZ2l0cwpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVOdW1iZXJzKQojcmVtb3ZlIHN0b3B3b3Jkcwpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCm15U3RvcHdvcmRzIDwtIGMoIndpbGwiLCAiY2FuIiwgInNoYWxsIiwgIm1heSIsICJ1cG9uIiwgIm9uIiwgInNheSIsICJvbmUiLCAid2F5IiwgImFsc28iLCAibXVjaCIsICJuZWVkIiwgInRha2UiLCAiZXZlbiIsICJsaWtlIiwgImdyZWF0IiwgImdldCIsICJ3aWxsIiwgIm1ha2UiLCAiZGF5IiwgIm5ldyIsICJhdHRlbXB0IiwgImFjaGlldmUiLCAibmV2ZXIiLCAibG90IiwgInB1dCIsICJzZXQiLCAiZ29vZCIsICJsb29rIiwgIm5vdyIsICJoZWxwIiwgImZpcnN0IiwgInRob3VnaCIsICJmYXIiLCAic3VyZSIsICJldmVyIiwgImVub3VnaCIsICJsYXN0IiwgImxpdHRsZSIsICJsYWNrIiwgInNlZW4iLCAiZXRjIiwgInN1cmUiLCAid2VsbCIsICJob3dldmVyIiwgIndvdWxkIiwgImNvdWxkIiwgIm11c3QiLCAibGV0IiwgIm1heSIsICJtaWdodCIsICJqdXN0IiwgIndhbnQiLCAia25vdyIsICJldmVyeSIsICJyaWdodCIsICJnb3Zlcm5tZW50IiwgInBlb3BsZSIsICJjb3VudHJ5IiwgIndvcmxkIiwgIm5hdGlvbiIsICJzdGF0ZXMiLCAidW5pdGVkIiwgIm5hdGlvbnMiLCAiYW1lcmljYSIsICJ0aW1lIiwgImxlc3MiLCAibW9yZSIsICJtYWtlIiwgIm1hZGUiLCAicHJlc2VudCIsICJ0b2RheSIsICJ0b2dldGhlciIsICJ3aXRoIiwgIndpdGhvdXQiLCAieWVhciIsICJ5ZWFycyIsICJuYXRpb25hbCIsICJtZW4iLCAid2l0aGluIiwgInN0aWxsIikKZG9jcyA8LXRtX21hcChkb2NzLCByZW1vdmVXb3JkcywgbXlTdG9wd29yZHMpCgojcmVtb3ZlIHdoaXRlc3BhY2UKZG9jcyA8LSB0bV9tYXAoZG9jcywgc3RyaXBXaGl0ZXNwYWNlKQoKI1N0ZW0gZG9jdW1lbnQKZG9jcyA8LSB0bV9tYXAoZG9jcyxzdGVtRG9jdW1lbnQpCmR0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoZG9jcykKI2NvbnZlcnQgcm93bmFtZXMgdG8gZmlsZW5hbWVzI2NvbnZlcnQgcm93bmFtZXMgdG8gZmlsZW5hbWVzCnJvd25hbWVzKGR0bSkgPC0gcGFzdGUoY29ycHVzLmxpc3QkdHlwZSwgY29ycHVzLmxpc3QkRmlsZSwKICAgICAgICAgICAgICAgICAgICAgICBjb3JwdXMubGlzdCRUZXJtLCBjb3JwdXMubGlzdCRzZW50LmlkLCBzZXA9Il8iKQoKcm93VG90YWxzIDwtIGFwcGx5KGR0bSAsIDEsIHN1bSkgI0ZpbmQgdGhlIHN1bSBvZiB3b3JkcyBpbiBlYWNoIERvY3VtZW50CgpkdG0gIDwtIGR0bVtyb3dUb3RhbHM+IDAsIF0KY29ycHVzLmxpc3Q9Y29ycHVzLmxpc3Rbcm93VG90YWxzPjAsIF0KYGBgCgoKCmBgYHtyLGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30KayA8LSA2CmR0bV9sZGEgPC0gTERBKGR0bSwgaywgY29udHJvbCA9IGxpc3Qoc2VlZCA9IDEyMzQpKQoKI3dyaXRlIG91dCByZXN1bHRzCiNkb2NzIHRvIHRvcGljcwpkdG1fbGRhLnRvcGljcyA8LSBhcy5tYXRyaXgodG9waWNzKGR0bV9sZGEpKQojdGFibGUoYygxOmssIGR0bV9sZGEudG9waWNzKSkKI3dyaXRlLmNzdihsZGFPdXQudG9waWNzLGZpbGU9cGFzdGUoIi4uL291dC9MREFHaWJicyIsaywiRG9jc1RvVG9waWNzLmNzdiIpKQoKI3RvcCA2IHRlcm1zIGluIGVhY2ggdG9waWMKZHRtX2xkYS50ZXJtcyA8LSBhcy5tYXRyaXgodGVybXMoZHRtX2xkYSwyMCkpCiN3cml0ZS5jc3YobGRhT3V0LnRlcm1zLGZpbGU9cGFzdGUoIi4uL291dC9MREFHaWJicyIsaywiVG9waWNzVG9UZXJtcy5jc3YiKSkKCiNwcm9iYWJpbGl0aWVzIGFzc29jaWF0ZWQgd2l0aCBlYWNoIHRvcGljIGFzc2lnbm1lbnQKdG9waWNQcm9iYWJpbGl0aWVzIDwtIGFzLmRhdGEuZnJhbWUoZHRtX2xkYUBnYW1tYSkKI3dyaXRlLmNzdih0b3BpY1Byb2JhYmlsaXRpZXMsZmlsZT1wYXN0ZSgiLi4vb3V0L0xEQUdpYmJzIixrLCJUb3BpY1Byb2JhYmlsaXRpZXMuY3N2IikpCgpkdG1fbGRhX3RkIDwtIHRpZHkoZHRtX2xkYSkKCmR0bV90b3BfdGVybXMgPC0gZHRtX2xkYV90ZCAlPiUKICBncm91cF9ieSh0b3BpYykgJT4lCiAgdG9wX24oMTIsIGJldGEpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKHRvcGljLCAtYmV0YSkKCmR0bV90b3BfdGVybXMgJT4lCiAgbXV0YXRlKHRlcm0gPSByZW9yZGVyKHRlcm0sIGJldGEpKSAlPiUKICBnZ3Bsb3QoYWVzKHRlcm0sIGJldGEsIGZpbGwgPSBmYWN0b3IodG9waWMpKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfd3JhcCh+IHRvcGljLCBuY29sID0gMywgc2NhbGVzID0gImZyZWUiKSArCiAgY29vcmRfZmxpcCgpCmBgYAoKRnJvbSB0aGUgYWJvdmUgZ3JhcGgsIHdlIGNhbiBzdXJlbHkgc2VlIHNvbWUgcGF0dGVybnMuIEZvciBpbnN0YW5jZSwgc29tZSB3b3JkcyBvY2N1ciBmcmVxdWVudGx5IGluIGV2ZXJ5IHRvcGljLCBsaWtlICJhbWVyaWNhbiIsICJ3b3JrIiwgImZyZWVkb20iIGV0Yy4sIHdoaWNoIG1ha2VzIHNlbnNlIGJlY2F1c2UgYSBwb2xpdGljYWwgc3BlZWNoIGlzIGFsbCBhYm91dCBjb250ZW50cyBsaWtlIHRoZW0uIE9uIHRoZSBvdGhlciBoYW5kLCB3ZSBjYW4gc2VlIHNvbWUgZGl2ZXJzaXRpZXMgYW1vbmcgdG9waWNzLiBMaWtlLCB0b3BpYzEgZm9jdXNlcyBtb3JlIG9uICJsYXciIHdoaWxlIHRvcGljMiBwYXlzIG1vcmUgYXR0ZW50aW9uIG9uICJwZWFjZSBhbmQgc2VjdXJpdHkiLiBTbyBJIG1hbnVhbGx5IHNldCB0b3BpYyBuYW1lcyB0byBlYWNoIG9mIHRoZSB0b3BpYzogIkxlZ2lzbGF0aW9uIiwgIkhvbWVsYW5kU2VjdXJpdHkiLCAiRWxlY3Rpb24iLCAiQW1lcmljYSIsICJSZWZvcm0iIGFuZCAiV29yayIuCgpCYXNlZCBvbiB0aGUgZGl2aWRlZCB0b3BpY3MsIHdlIGNhbiBjbGVhcmx5IGZpbmQgc29tZSBoaXQgd29yZHMgaW4gcG9saXRpY2FsIHNwZWVjaGVzLiBTbyBub3cgd2Ugd2FudCB0byBmaW5kIG91dCBob3cgdGhlIGZyZXF1ZW5jaWVzIG9mIHNvbWUgb2YgaGl0IHdvcmRzIGNoYW5nZSBvdmVyIHRpbWUuCgpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIG1lc3NhZ2U9IEZBTFNFfQpsaWJyYXJ5KCJwbHlyIikKIyBMb2FkIGRhdGE6CiNkYXRlcyA8LSByZWFkLnRhYmxlKCJJbmF1Z3VhdGlvbkRhdGVzLnR4dCIsIGhlYWRlciA9IFQsIHNlcCA9ICJcdCIpCiNpbmZvIDwtIHJlYWQueGxzeCgiSW5hdWd1cmF0aW9uSW5mby54bHN4Iiwgc2hlZXRJbmRleCA9IDEpCmluZm8gPC0gcmVhZC54bHN4KCIuLi9kYXRhL0luYXVndXJhdGlvbkluZm8ueGxzeCIsIHNoZWV0SW5kZXggPSAxKQpmb2xkZXIucGF0aD0iLi4vZGF0YS9JbmF1Z3VyYWxTcGVlY2hlcy8iCnNwZWVjaGVzPWxpc3QuZmlsZXMocGF0aCA9IGZvbGRlci5wYXRoLCBwYXR0ZXJuID0gIioudHh0IikKcHJlei5vdXQ9c3Vic3RyKHNwZWVjaGVzLCA2LCBuY2hhcihzcGVlY2hlcyktNCkKCmxlbmd0aC5zcGVlY2hlcz1yZXAoTkEsIGxlbmd0aChzcGVlY2hlcykpCmZmLmFsbDwtQ29ycHVzKERpclNvdXJjZShmb2xkZXIucGF0aCkpCgoKZmYuYWxsPC10bV9tYXAoZmYuYWxsLCBzdHJpcFdoaXRlc3BhY2UpCmZmLmFsbDwtdG1fbWFwKGZmLmFsbCwgY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKZmYuYWxsPC10bV9tYXAoZmYuYWxsLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCmZmLmFsbDwtdG1fbWFwKGZmLmFsbCwgcmVtb3ZlV29yZHMsIGNoYXJhY3RlcigwKSkKZmYuYWxsPC10bV9tYXAoZmYuYWxsLCByZW1vdmVQdW5jdHVhdGlvbikKdGRtLmFsbDwtVGVybURvY3VtZW50TWF0cml4KGZmLmFsbCkKIyB0dXJuaW5nIGVhY2ggb2YgdGhlIGRvY3VtZW50cyBpbnRvIGEgb25lLXRva2VuLXBlci1kb2N1bWVudC1wZXItcm93IHRhYmxlOgp0ZG0udGlkeSA8LSB0aWR5KHRkbS5hbGwpCnRkbS5vdmVyYWxsIDwtIHN1bW1hcmlzZShncm91cF9ieSh0ZG0udGlkeSwgdGVybSksIHN1bShjb3VudCkpCmR0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoZmYuYWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KHdlaWdodGluZyA9IGZ1bmN0aW9uKHgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodFRmSWRmKHgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemUgPUZBTFNFKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9wd29yZHMgPSBUUlVFKSkKZmYuZHRtPXRpZHkoZHRtKQojIGNhbGN1bGF0aW5nIHRoZSB0Zi1pZGYgb2YgZWFjaCB0ZXJtLXNwZWVjaCBwYWlyOgppbmF1Z190Zl9pZGYgPC0gdGRtLnRpZHkgJT4lCiAgYmluZF90Zl9pZGYodGVybSwgZG9jdW1lbnQsIGNvdW50KSAlPiUKICBhcnJhbmdlKGRlc2ModGZfaWRmKSkKI2luYXVnX3RmX2lkZiAlPiUKICMgYXJyYW5nZShkZXNjKHRmX2lkZikpCnRlc3RfeWVhciA8LSBkZHBseShpbmF1Z190Zl9pZGYsIC4oZG9jdW1lbnQpLGNhbGN1bGF0ZV95ZWFyKQp5ZWFyX3Rlcm1fY291bnRzIDwtIGRkcGx5KHRlc3RfeWVhciwuKHllYXIpLGNhbGN1bGF0ZV90b3RhbCkKCiN0aWZmKGZpbGVuYW1lID0gInRlc3QxLnRpZiIsd2lkdGggPSAxNSxoZWlnaHQgPSAxOCx1bml0cyA9ImNtIixjb21wcmVzc2lvbj0ibHp3IixiZz0id2hpdGUiLHJlcz02MDApCgp5ZWFyX3Rlcm1fY291bnRzICU+JQogIGZpbHRlcih0ZXJtICVpbiUgYygibGF3IiwgIndvcmsiLCAiaW1taWdyYXRpb24iLCAidHJhZGUiLCAiZWNvbm9teSIsICJjb25zdGl0dXRpb24iKSkgJT4lCiAgZ2dwbG90KGFlcyh5ZWFyLCBjb3VudCAvIHllYXJfdG90YWwpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aCgpICsKICBmYWNldF93cmFwKH4gdGVybSwgbmNvbCA9IDIsc2NhbGVzID0gImZyZWVfeSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSArCiAgeWxhYigiJSBmcmVxdWVuY3kgb2Ygd29yZCBpbiBpbmF1Z3VyYWwgYWRkcmVzcyIpCgojZGV2Lm9mZigpCgpgYGAKCkFzIHdlIGNhbiBzZWUsIHRoZXkgZGlzcGxheSBkaWZmZXJlbnQgcGF0dGVybnMgYWx0aG91Z2ggdGhleSBhcmUgYWxsIGhpdCB0b3BpY3MuIEZvciBleGFtcGxlLCB0aGUgZnJlcXVlbmNpZXMgb2YgImxhdyIgYW5kICJjb25zaXRpdHV0aW9uIiBzZWVtcyB0byBiZSBsb3dlciB0aGFuIGJlZm9yZSwgd2hpY2ggbWFrZXMgc2Vuc2UgYmVjYXVzZSBsYXdzIGFyZSBtb3JlIGNvbXBsZXRlIHRoYW4gYmVmb3JlLiAiaW1taWdyYXRpb24iIGFuZCAid29yayIgb2NjdXIgbW9yZSBvZnRlbiBub3cgd2hpY2ggYWxzbyBmaXRzIHRoZSB0cmVuZC4gV2hpbGUgImVjb25vbXkiIGFuZCAidHJhZGUiIG9jY3VyIHN0ZWFkaWx5IGR1cmluZyB0aGUgY291cnNlIG9mIGRldmVsb3BtZW50LgoKYGBge3IsZWNobz1GQUxTRX0KdGVybXMuYmV0YT1kdG1fbGRhQGJldGEKdGVybXMuYmV0YT1zY2FsZSh0ZXJtcy5iZXRhKQp0b3BpY3MudGVybXM9TlVMTApmb3IoaSBpbiAxOmspewogIHRvcGljcy50ZXJtcz1yYmluZCh0b3BpY3MudGVybXMsIGR0bV9sZGFAdGVybXNbb3JkZXIodGVybXMuYmV0YVtpLF0sIGRlY3JlYXNpbmcgPSBUUlVFKVsxOjZdXSkKfQoKdG9waWNzLmhhc2g9YygiTGVnaXNsYXRpb24iLCAiSG9tZWxhbmRTZWN1cml0eSIsICJFbGVjdGlvbiIsICJBbWVyaWNhIiwgIlJlZm9ybSIsICJXb3JrIikKY29ycHVzLmxpc3QkbGRhdG9waWM9YXMudmVjdG9yKGR0bV9sZGEudG9waWNzKQpjb3JwdXMubGlzdCRsZGFoYXNoPXRvcGljcy5oYXNoW2R0bV9sZGEudG9waWNzXQoKY29sbmFtZXModG9waWNQcm9iYWJpbGl0aWVzKT10b3BpY3MuaGFzaApjb3JwdXMubGlzdC5kZj1jYmluZChjb3JwdXMubGlzdCwgdG9waWNQcm9iYWJpbGl0aWVzKQpgYGAKCgphbmFseXNpcyAjIyBleHBsYW5hdGlvbiBmb2xsb3dlZCBieSBvbmxpbmUgYm9vayBmcmVxdWVuY3kgcHJvYiBldGMuLgoKYGBge3IsZWNobz1GQUxTRX0Kc3BlZWNoLmRmPXRibF9kZihjb3JwdXMubGlzdC5kZiklPiVmaWx0ZXIodHlwZT09Im5vbWluIiwgd29yZC5jb3VudDwxNSklPiVzZWxlY3Qoc2VudGVuY2VzLCBMZWdpc2xhdGlvbjpXb3JrKQoKYXMuY2hhcmFjdGVyKHNwZWVjaC5kZiRzZW50ZW5jZXNbYXBwbHkoYXMuZGF0YS5mcmFtZShzcGVlY2guZGZbLC0xXSksIDIsIHdoaWNoLm1heCldKQoKbmFtZXMoc3BlZWNoLmRmKVstMV0KYGBgCgpBbHNvLCB3ZSBjYW4gY2x1c3RlciBkaWZmZXJlbnQgaW5hdWd1cmF0aW9uIHNwZWVjaGVzIGluIHRlcm1zIG9mIHRoZWlyIHRvcGljOgoKYGBge3IsZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInfQpwcmVzaWQuc3VtbWFyeT10YmxfZGYoY29ycHVzLmxpc3QuZGYpJT4lCiAgZmlsdGVyKHR5cGU9PSJpbmF1ZyIsIEZpbGUlaW4lc2VsLmNvbXBhcmlzb24pJT4lCiAgc2VsZWN0KEZpbGUsIExlZ2lzbGF0aW9uOldvcmspJT4lCiAgZ3JvdXBfYnkoRmlsZSklPiUKICBzdW1tYXJpc2VfZWFjaChmdW5zKG1lYW4pKQoKcHJlc2lkLnN1bW1hcnk9YXMuZGF0YS5mcmFtZShwcmVzaWQuc3VtbWFyeSkKcm93bmFtZXMocHJlc2lkLnN1bW1hcnkpPWFzLmNoYXJhY3RlcigocHJlc2lkLnN1bW1hcnlbLDFdKSkKa20ucmVzPWttZWFucyhzY2FsZShwcmVzaWQuc3VtbWFyeVssLTFdKSwgaXRlci5tYXg9MjAwLAogICAgICAgICAgICAgIDQpCmZ2aXpfY2x1c3RlcihrbS5yZXMsIAogICAgICAgICAgICAgc3RhbmQ9VCwgcmVwZWw9IFRSVUUsCiAgICAgICAgICAgICBkYXRhID0gcHJlc2lkLnN1bW1hcnlbLC0xXSwKICAgICAgICAgICAgIHNob3cuY2x1c3QuY2VudD1GQUxTRSkKYGBgCgpGcm9tIHRoZSBmaWd1cmUsIHdlIGNhbiBzZWUgdGhhdCB0b3BpY3Mgb2YgaW5hdWd1cmF0aW9uIHNwZWVjaGVzIGRvIGhhdmUgZ3JlYXQgZGl2ZXJzaXR5IGluIHRlcm1zIG9mIGRpZmZlcmVudCBwcmVzaWRlbnRzLiBGb3IgZXhhbXBsZSwgRG9uYWxkIFRydW1wIGFuZCBKb2huIGFkYW1zLCB3aGljaCBjb21lIGZyb20gZGlmZmVyZW50IGNsdXN0ZXJzIHdpdGggZmFyIGRpc3RhbmNlLiBJdCBtYWtlcyBzZW5zZSBiZWNhdXNlIGJhY2sgd2hlbiBKb2huIHdhcyBwcmVzaWRlbnQsIGhlIHRhbGtlZCBtb3JlIGFib3V0IHRoZSBpbmRlcGVuZGVuY2Ugb2YgQW1lcmljYS4gQnV0IG5vdywgdG9waWNzIGNvbmNlcm5pbmcgaG93IHRvIGRldmVsb3AgdGhlIGNvdW50cnkgYXJlIG1vc3RseSBtZW50aW9uZWQuCgojIyBQYXJ0MiBBbmFseXppbmcgV29yZHMKCk5vdyBsZXQncyBkbyBzb21lIGFuYWx5c2lzIG9uIHRoZSBudW1iZXIgb2Ygd29yZHMgaW4gb25lIHNlbnRlbmNlLiBGaXJzdCwgbGV0J3MgZm9jdXMgb24gYWxsIHRoZSBpbmF1Z3VyYXRpb24gc3BlZWNoZXMgaW4gZWFjaCBvZiBkaWZmZXJlbnQgcGFydGllczoKCmBgYHtyLGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJ30Kc2VudGVuY2UubGlzdC5zZWw9ZmlsdGVyKHNlbnRlbmNlLmxpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICB0eXBlID09ICJpbmF1ZyIpCnNlbnRlbmNlLmxpc3Quc2VsJFBhcnR5PWZhY3RvcihzZW50ZW5jZS5saXN0LnNlbCRQYXJ0eSkKCnNlbnRlbmNlLmxpc3Quc2VsJFBhcnR5T3JkZXJlZD1yZW9yZGVyKHNlbnRlbmNlLmxpc3Quc2VsJFBhcnR5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlLmxpc3Quc2VsJHdvcmQuY291bnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcj1UKQoKYmVlc3dhcm0od29yZC5jb3VudH5QYXJ0eU9yZGVyZWQsIAogICAgICAgICBkYXRhPXNlbnRlbmNlLmxpc3Quc2VsLAogICAgICAgICBob3Jpem9udGFsID0gVFJVRSwgCiAgICAgICAgIHBjaD0xNiwgY29sPWFscGhhKGJyZXdlci5wYWwoOSwgIlNldDEiKSwgMC42KSwgCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LAogICAgICAgICBzcGFjaW5nPTAuMi9ubGV2ZWxzKHNlbnRlbmNlLmxpc3Quc2VsJFBhcnR5T3JkZXJlZCksCiAgICAgICAgIGxhcz0yLCB4bGFiPSJOdW1iZXIgb2Ygd29yZHMgaW4gYSBzZW50ZW5jZS4iLCB5bGFiPSIiLAogICAgICAgICBtYWluPSJEaWZmZXJlbnQgcGFydGllcyIpCiNzZW50ZW5jZS5saXN0JT4lCiAjIGZpbHRlcihQYXJ0eT09IlJlcHVibGljYW4iLCAKICAjICAgICAgIHR5cGU9PSJpbmF1ZyIsIAogICAjICAgICAgd29yZC5jb3VudDw9MyklPiUKICAjc2VsZWN0KHNlbnRlbmNlcyklPiVzYW1wbGVfbig2KQpgYGAKClRoZSBtZXNzYWdlIGlzIGNsZWFyIHRoYXQgZm9yICJGZWRyYWxpc3QiLCAiV2hpZyIsICJEZW1vY3JhdGljLVJlcHVibGljYW4gUGFydHkiLCB0aGVyZSBhcmUgYmFzaWNhbGx5IG5vIHByZWZlcmVuY2VzIG9uIHVzaW5nIHNob3J0IG9yIGxvbmcgc2VudGVuY2VzLiBIb3dldmVyLCBmb3IgIkRlbW9jcmF0aWMiIGFuZCAiUmVwdWJsaWNhbiIsIHRoZXkgc2VlbSB0byBwcmVmZXIgdXNpbmcgbW9yZSBzaG9ydCB3b3JkcyBwZXIgc2VudGVuY2UuClRha2UgRG9uYWxkIFRydW1wIGZvciBpbnN0YW5jZSwgdGhlIHBhdHRlcm5zIGluIGhpcyBkaWZmZXJlbnQgc3BlZWNoZXMgYXJlIGVzcGVjaWFsbHkgb2J2aW91czoKCmBgYHtyLGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInfQpzZW50ZW5jZS5saXN0LnNlbD1maWx0ZXIoc2VudGVuY2UubGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIEZpbGUgPT0gIkRvbmFsZEpUcnVtcCIpCnNlbnRlbmNlLmxpc3Quc2VsJHR5cGU9ZmFjdG9yKHNlbnRlbmNlLmxpc3Quc2VsJHR5cGUpCgpzZW50ZW5jZS5saXN0LnNlbCR0eXBlT3JkZXJlZD1yZW9yZGVyKHNlbnRlbmNlLmxpc3Quc2VsJHR5cGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VudGVuY2UubGlzdC5zZWwkd29yZC5jb3VudCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyPVQpCgpiZWVzd2FybSh3b3JkLmNvdW50fnR5cGVPcmRlcmVkLCAKICAgICAgICAgZGF0YT1zZW50ZW5jZS5saXN0LnNlbCwKICAgICAgICAgaG9yaXpvbnRhbCA9IFRSVUUsIAogICAgICAgICBwY2g9MTYsIGNvbD1hbHBoYShicmV3ZXIucGFsKDksICJTZXQxIiksIDAuNiksIAogICAgICAgICBjZXg9MC41NSwgY2V4LmF4aXM9MC44LCBjZXgubGFiPTAuOCwKICAgICAgICAgc3BhY2luZz0wLjUvbmxldmVscyhzZW50ZW5jZS5saXN0LnNlbCR0eXBlT3JkZXJlZCksCiAgICAgICAgIGxhcz0yLCB4bGFiPSJOdW1iZXIgb2Ygd29yZHMgaW4gYSBzZW50ZW5jZS4iLCB5bGFiPSIiLAogICAgICAgICBtYWluPSJEaWZmZXJlbnQgc3BlZWNoZXMgb2YgRG9uYWxkSlRydW1wIikKYGBgCgpXZSBjYW4gc2VlIHRoYXQgaGlzIGluYXVndXJhdGlvbiBzcGVlY2hlcyBzZWVtIG5vcm1hbCwgd2hpbGUgaGlzIG5vbWluZWUgc3BlZWNoZXMgZ2V0IHRvIHNob3cgc29tZSB0ZW5kIHRvIHVzZSBzaG9ydCB3b3Jkcy4gV2hhdCdzIG1vcmUsIGhpcyBwdWJsaWMgc3BlZWNoZXMgc2hvdyBhIGFwcGFyZW50IHByZWZlcmVuY2Ugb24gdXNpbmcgc2hvcnQgd29yZHMuIEFuZCB0aGUgbGVuZ3RoIG9mIGVhY2ggb2YgdGhlIHRocmVlIHR5cGVzIG9mIHNwZWVjaGVzIHNlZW1zIHRvIGluY3JlYXNlLCB3aGljaCBtYXkgc3VnZ2VzdCBoZSBtaWdodCBzb3J0IG9mIGNvbnRyb2wgaGltc2VsZiBhdCBtb3JlIGZvcm1hbCB2ZW51ZXMuIEFuZCBsZXQncyB0YWtlIGEgbG9vayBhdCB3aGF0IGV4YWN0bHkgc2hvcnQgc2VudGVuY2VzIGhlIHNhaWQgYXQgZGlmZmVyZW50IHR5cGVzIG9mIHNwZWVjaGVzLgoKbm9taW5lZSBzcGVlY2hlczoKYGBge3IsZWNobz1GQUxTRX0Kc2VudGVuY2UubGlzdCU+JQogIGZpbHRlcihGaWxlPT0iRG9uYWxkSlRydW1wIiwgCiAgICAgICAgIHR5cGU9PSJub21pbiIsIAogICAgICAgICB3b3JkLmNvdW50PD0zKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpJT4lc2FtcGxlX24oNSkKYGBgCgppbmF1Z3VyYXRpb24gc3BlZWNoZXM6CmBgYHtyLGVjaG89RkFMU0V9CnNlbnRlbmNlLmxpc3QlPiUKICBmaWx0ZXIoRmlsZT09IkRvbmFsZEpUcnVtcCIsIAogICAgICAgICB0eXBlPT0iaW5hdWciLCAKICAgICAgICAgd29yZC5jb3VudDw9MyklPiUKICBzZWxlY3Qoc2VudGVuY2VzKSU+JXNhbXBsZV9uKDUpCmBgYApwdWJsaWMgc3BlZWNoZXM6CmBgYHtyLGVjaG89RkFMU0V9CnNlbnRlbmNlLmxpc3QlPiUKICBmaWx0ZXIoRmlsZT09IkRvbmFsZEpUcnVtcCIsIAogICAgICAgICB0eXBlPT0ic3BlZWNoZXMiLCAKICAgICAgICAgd29yZC5jb3VudDw9NSklPiUKICBzZWxlY3Qoc2VudGVuY2VzKSU+JXNhbXBsZV9uKDUpCmBgYAoKV2UgY2FuIHNlZSB0aGF0LCBhdCBub21pbmVlIGFuZCBpbmF1Z3VyYXRpb24gc3BlZWNoZXMsIHRoZSBzaG9ydCBzZW50ZW5jZXMgZG8gbm90IGNvbnZleSBtdWNoIHJlYWwgaW5mb3JtYXRpb24sIGxpa2UgInRoYW5rIHlvdSIuIFdoaWxlIGluIHB1YmxpYyBzcGVlY2hlcywgc2hvcnQgc2VudGVuY2VzIGRvIG1lYW4gc29tZXRoaW5nLiBJdCBtYXkgZXhwcmVzcyBoaXMgZW1vdGlvbiwgY29tbWVudHMgZXRjLgoKCioqQmFzZWQgb24gdGhlIGFib3ZlIGFuYWx5c2lzLCBzaW5jZSBzaG9ydCB3b3JkcyBhcmUgc29tZSBraW5kIG9mIGhpdCBpbiBzcGVlY2hlcy4gTm93IGxldCdzIHRha2UgYW4gZXNwZWNpYWwgbG9vayBvbiB0aGUgcHJlc2VudCBwcmVzaWRlbnQgRG9uYWxkIFRydW1wIGFuZCBmb2N1cyBvbiB0aGUgZnJlcXVlbmN5IG9mIHdvcmQgZ3J1b3BzIChiaWdyYW0pLiBCZWNhdXNlIHVubGlrZSBzaW5nbGUgd29yZCwgdGhpcyBtYXkgYWN0dWFsbHkgbWVhbiBzb21ldGhpbmcgbGlrZSBzb21lIHNwZWNpZmljIHRvcGljcy4qKiAKCkZpcnN0LCBsZXQncyB2aXN1YWxpemUgd2hhdCBiaWdyYW1zIGhlIHNhaWQgZnJlcXVlbnRseSBpbiBoaXMgZGlmZmVyZW50IHNwZWVjaGVzOgoKYGBge3IsZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRX0KdHJ1bXBfYmlncmFtcyA8LSBzcGVlY2gubGlzdFtzcGVlY2gubGlzdCRGaWxlID09ICJEb25hbGRKVHJ1bXAiLF0gJT4lCiAgdW5uZXN0X3Rva2VucyhiaWdyYW0sIGZ1bGx0ZXh0LCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikKCmJpZ3JhbXNfc2VwYXJhdGVkIDwtIHRydW1wX2JpZ3JhbXMgJT4lCiAgc2VwYXJhdGUoYmlncmFtLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpCgpiaWdyYW1zX2ZpbHRlcmVkIDwtIGJpZ3JhbXNfc2VwYXJhdGVkICU+JQogIGZpbHRlcighd29yZDEgJWluJSBzdG9wX3dvcmRzJHdvcmQpICU+JQogIGZpbHRlcighd29yZDIgJWluJSBzdG9wX3dvcmRzJHdvcmQpCgpiaWdyYW1fY291bnRzIDwtIGJpZ3JhbXNfZmlsdGVyZWQgJT4lIAogIGRwbHlyOjpjb3VudCh3b3JkMSwgd29yZDIsIHNvcnQgPSBUUlVFKQoKYmlncmFtc191bml0ZWQgPC0gYmlncmFtc19maWx0ZXJlZCAlPiUKICB1bml0ZShiaWdyYW0sIHdvcmQxLCB3b3JkMiwgc2VwID0gIiAiKSAKCmJpZ3JhbXNfdW5pdGVkIDwtIGJpZ3JhbXNfdW5pdGVkICU+JQogIGRwbHlyOjpjb3VudCh0eXBlLCBiaWdyYW0pICU+JQogIGFycmFuZ2UoZGVzYyhuKSkgCgpiaWdyYW1zX3VuaXRlZCA8LSBiaWdyYW1zX3VuaXRlZCAlPiUgCiAgbXV0YXRlKGJpZ3JhbSA9IGZhY3RvcihiaWdyYW0sIGxldmVscyA9IHJldih1bmlxdWUoYmlncmFtKSkpKSAlPiUKICBncm91cF9ieSh0eXBlKSAlPiUgCiAgYXJyYW5nZShkZXNjKG4pKSU+JQogIHRvcF9uKDUpICU+JSAKICB1bmdyb3VwCgoKZ2dwbG90KGJpZ3JhbXNfdW5pdGVkLCBhZXMoYmlncmFtLCBuLCBmaWxsID0gdHlwZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGxhYnMoeCA9IE5VTEwsIHkgPSAiY291bnQgb2Ygd29yZHMiKSArCiAgZmFjZXRfd3JhcCh+dHlwZSwgbmNvbCA9IDIsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKQpgYGAKClRocm91Z2ggdmlzdWFsaXppbmcgdGhhdCwgYW5hbHl6aW5nIGJpZ3JhbSBpcyBoZWxwZnVsIGZvciBleHBsb3JhdG9yeSBhbmFseXNlcyBvZiB0aGUgdGV4dC4gRm9yIGV4YW1wbGUsIGlmIHdlIHdhbnQgdG8ga25vdyB3aGF0IHdvcmQgaXMgYWhlYWQgb2YgImFtZXJpY2FuIiBtb3N0OgoKYGBge3IsZWNobz1GQUxTRX0KYmlncmFtc19maWx0ZXJlZCAlPiUKICBmaWx0ZXIod29yZDIgPT0gImFtZXJpY2FuIikgJT4lCiAgZHBseXI6OmNvdW50KHR5cGUsIHdvcmQxLCBzb3J0ID0gVFJVRSkKYGBgCldlIGNhbiBzZWUgaXQncyBBZnJpY2EgQW1lcmljYW4sIHdoaWNoIGlzIGV4YWN0bHkgb25lIG9mIGhpcyBmb2N1cyBpbiB0aGUgc3BlZWNoZXMuCgpPciwgaWYgd2UgYXJlIHdvbmRlcmluZyB3aGF0IGtpbmtzIG9mIHBvbGljeSBoZSBtZW50aW9uZWQgbW9zdDoKYGBge3IsZWNobz1GQUxTRX0KYmlncmFtc19maWx0ZXJlZCAlPiUKICBmaWx0ZXIod29yZDIgPT0gInBvbGljeSIpICU+JQogIGRwbHlyOjpjb3VudCh0eXBlLCB3b3JkMSwgc29ydCA9IFRSVUUpCmhlYWQoYmlncmFtc19maWx0ZXJlZCw1KQpgYGAKVGhlIHJlc3VsdHMgYWxzbyBmaXQgdGhlIHJlYWwgdHJlbmQsIHdoaWNoIGFyZSBpbW1pZ3JhdGlvbiBhbmQgZm9yZWlnbiBwb2xpY2llcy4KCk9uZSBzdGVwIGZ1cnRoZXIsIGlmIHdlIHdhbnQgdG8ga25vdyB3aGF0IGlzIGhpcyBhdHRpdHVkZSBvciBob3cgaGUgZGVzY3JpYmUgaW1taWdyYXRpb24sIHdlIGNhbiBjaGVjayB0aGUgd29yZHMgdGhhdCBhcmUgYWhlYWQgb2YgImltbWlncmF0aW9uIjoKYGBge3IsZWNobz1GQUxTRX0KYmlncmFtc19maWx0ZXJlZCAlPiUKICBmaWx0ZXIod29yZDIgPT0gImltbWlncmF0aW9uIikgJT4lCiAgZHBseXI6OmNvdW50KHR5cGUsIHdvcmQxLCBzb3J0ID0gVFJVRSkKaGVhZChiaWdyYW1zX2ZpbHRlcmVkLDUpCmBgYAoKVGhlIHJldXNsdHMgaGF2ZSBubyBzdXJwcmlzZSwgYmVjYXVzZSBoZSBoYXMgYW4gZXh0cmVtZSBhdHRpdHVkZSBhYm91dCBpbW1pZ3JhdGlvbi4gU28gbm8gd29uZGVyIGhlIGFsd2F5cyBlbXBoYXNpemVkICJpbGxlZ2FsIiB3aGVuIHRhbGtpbmcgYWJvdXQgaXQuCgojIyBQYXJ0MyBTZW50aW1lbnQgQW5hbHlzaXMKCkZpbmFsbHksIHdlIHdpbGwgaW1wbGVtZW50IHNlbnRpbWVudCBhbmFseXNpcyBvbiB0aGUgaW5hdWd1cmF0aW9uIHNwZWVjaGVzIGFuZCBhbHNvIGhhdmUgYW4gZXNwZWNpYWwgbG9vayBhdCBEb25hbGQgVHJ1bXBzIGVtb3Rpb21zIGluIGhpcyBkaWZmZXJlbnQgc3BlZWNoZXMuCgpJIHdpbGwgdXNlICJOUkMiIGxleGljb24gdG8gZG8gc2VudGltZW50IGFuYWx5c2lzLiBUbyBkbyB0aGF0LCBJIHF1YW50aWZ5IHRoZSBwb3NpdGl2aXR5IGFuZCBuZWd0aXZpdHkgb2YgZWFjaCB3b3JkIGJ5IGNhbGN1bGF0aW5nIGEgc2NvcmUgZm9yIGVhY2ggb2YgdGhlbS4gVGhlIGZvbGxvd2luZyBmaWd1cmUgc2hvd3MgdGhlIHBvc2l0aXZpdHkgb2YgYWxsIHRoZSBpbmF1Z3VyYXRpb24gc3BlZWNoZXM6CgpgYGB7cixmaWcud2lkdGggPSA1LCBmaWcuaGVpZ2h0ID0gNiwgZWNobz0gRkFMU0UsIHdhcm5pbmc9IEZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcid9CgppbmF1Z19zcGVlY2gubGlzdCA8LSBzcGVlY2gubGlzdCAlPiUKICAgICAgICBmaWx0ZXIodHlwZSA9PSAiaW5hdWciKQpkb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UoaW5hdWdfc3BlZWNoLmxpc3QkZnVsbHRleHQpKQpkb2NzIDwtdG1fbWFwKGRvY3MsY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKI3JlbW92ZSBwdW5jdHVhdGlvbgpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVQdW5jdHVhdGlvbikKI1N0cmlwIGRpZ2l0cwpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVOdW1iZXJzKQojcmVtb3ZlIHN0b3B3b3Jkcwpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCgojcmVtb3ZlIHdoaXRlc3BhY2UKZG9jcyA8LSB0bV9tYXAoZG9jcywgc3RyaXBXaGl0ZXNwYWNlKQoKI1N0ZW0gZG9jdW1lbnQKZG9jcyA8LSB0bV9tYXAoZG9jcyxzdGVtRG9jdW1lbnQpCmR0bSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoZG9jcykKcm93bmFtZXMoZHRtKSA8LSBwYXN0ZSgiaW5hdWciLCBpbmF1Z19zcGVlY2gubGlzdCRGaWxlLAogICAgICAgICAgICAgICAgICAgICAgIGluYXVnX3NwZWVjaC5saXN0JFRlcm0sIHNlcD0iXyIpCgpkdG1fdGQgPC0gdGlkeShkdG0pCgpkdG1fc2VudGltZW50X2NvdW50IDwtIGR0bV90ZCAlPiUKICAgICAgICBtdXRhdGUod29yZCA9IHRlcm0pICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpLCBieSA9ICJ3b3JkIikgJT4lCiAgZHBseXI6OmNvdW50KHNlbnRpbWVudCwgZG9jdW1lbnQpICU+JQogIHNwcmVhZChzZW50aW1lbnQsIG4sIGZpbGwgPSAwKQoKCmR0bV9zZW50aW1lbnRfY291bnQgJT4lCiAgbXV0YXRlKHNjb3JlID0gKHBvc2l0aXZlIC0gbmVnYXRpdmUpIC8gKHBvc2l0aXZlICsgbmVnYXRpdmUpKSAlPiUKICBtdXRhdGUoZG9jdW1lbnQgPSByZW9yZGVyKGRvY3VtZW50LCBzY29yZSkpICU+JQogIGdncGxvdChhZXMoZG9jdW1lbnQsIHNjb3JlLCBmaWxsID0gc2NvcmUgPiAwKSkgKwogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoeCA9ICJEb2N1bWVudCIsCiAgICAgICB5ID0gIlBvc2l0aXZpdHkgc2NvcmUgYW1vbmcgaW5hdWcgc3BlZWNoZXMiKQpgYGAKCkZyb20gdGhlIGZpZ3VyZSwgd2UgY2FuIHZpc3VhbGl6ZSB0aGF0IFphY2hhcnkgVHlsb3IgaGFzIHRoZSBoaWdoZXN0IHZhbHVlIG9mIHBvc2l0aXZpdHksIHdoaWNoIG1heSBzdWdnZXN0IHRoYXQgaGUgd2FzIGEgZ29vZCBzcGVlY2hlciBhbmQgaGFkIGEgZ3JlYXQgd2F5IHRvIHBlcnN1YWRlIHBlb3BsZS4gT24gdGhlIG90aGVyIGhhbmQsIFdhcnJlbiBIYXJkaW5nIHNlZW1zIHRvIGhhdmUgdGhlIGxvd2VzdCB2YWx1ZSBvZiBwb3NpdGl2aXR5LiBBbnl3YXksIHRoZSBicmlnaHQgc2lkZSBpcyB0aGF0IG5vbmUgb2YgdGhlIHBhc3QgcHJlc2lkZW50cyBlbmRzIHVwIHdpdGggYSBuZWdhdGl2ZSB2YWx1ZSwgd2hpY2ggaW1wbGllcyB0aGF0IGluYXVndXJhdGlvbiBzcGVlY2hlcyBhcmUgc29tZSBzb3J0IG9mIGdvb2Qgd2F5IHRvIGNvbnZleSBwb3N0aXZlIGF0dGl0dXRlIGFuZCB0byBwcm92aWRlIGhvcGUgYW5kIGZhaXRoLgoKTm93IGxldCdzIGxvb2sgYXQgdGhlIGRpZmZlcmVudCBzcGVlY2hlcyBvZiBEb25hbGQgVHJ1bXAuIFdlIGFsc28gdmlzYXVsaXplIHNjb3JlIG9mIHNwZWVjaGVzIGluIHRlcm1zIG9mIHR5cGVzLgpgYGB7cixlY2hvPUZBTFNFLGZpZy5hbGlnbj0nY2VudGVyJ30KdHJ1bXBfc3BlZWNoLmxpc3QgPC0gc3BlZWNoLmxpc3QgJT4lCiAgICAgICAgZmlsdGVyKEZpbGUgPT0gIkRvbmFsZEpUcnVtcCIpCmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0cnVtcF9zcGVlY2gubGlzdCRmdWxsdGV4dCkpCmRvY3MgPC10bV9tYXAoZG9jcyxjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQojcmVtb3ZlIHB1bmN0dWF0aW9uCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHJlbW92ZVB1bmN0dWF0aW9uKQojU3RyaXAgZGlnaXRzCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHJlbW92ZU51bWJlcnMpCiNyZW1vdmUgc3RvcHdvcmRzCmRvY3MgPC0gdG1fbWFwKGRvY3MsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkKCiNyZW1vdmUgd2hpdGVzcGFjZQpkb2NzIDwtIHRtX21hcChkb2NzLCBzdHJpcFdoaXRlc3BhY2UpCgojU3RlbSBkb2N1bWVudApkb2NzIDwtIHRtX21hcChkb2NzLHN0ZW1Eb2N1bWVudCkKZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChkb2NzKQpyb3duYW1lcyhkdG0pIDwtIHBhc3RlKHRydW1wX3NwZWVjaC5saXN0JHR5cGUsIHRydW1wX3NwZWVjaC5saXN0JEZpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgIHNlcD0iXyIpCmR0bV90ZCA8LSB0aWR5KGR0bSkKCmR0bV9zZW50aW1lbnRfY291bnQgPC0gZHRtX3RkICU+JQogICAgICAgIG11dGF0ZSh3b3JkID0gdGVybSkgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIiksIGJ5ID0gIndvcmQiKSAlPiUKICBkcGx5cjo6Y291bnQoc2VudGltZW50LCBkb2N1bWVudCkgJT4lCiAgc3ByZWFkKHNlbnRpbWVudCwgbiwgZmlsbCA9IDApCgoKZHRtX3NlbnRpbWVudF9jb3VudCAlPiUKICBtdXRhdGUoc2NvcmUgPSAocG9zaXRpdmUgLSBuZWdhdGl2ZSkgLyAocG9zaXRpdmUgKyBuZWdhdGl2ZSkpICU+JQogIG11dGF0ZShkb2N1bWVudCA9IHJlb3JkZXIoZG9jdW1lbnQsIHNjb3JlKSkgJT4lCiAgZ2dwbG90KGFlcyhkb2N1bWVudCwgc2NvcmUsIGZpbGwgPSBzY29yZSA+IDApKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSwgd2lkdGggPSAwLjIpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoeCA9ICJEb2N1bWVudCIsCiAgICAgICB5ID0gIlBvc2l0aXZpdHkgc2NvcmUgYW1vbmcgRG9uYWxkVHJ1bXAncyBzcGVlY2hlcyIpCmBgYAoKVGhlIHBhdHRlcm5zIGluIHRoZSBncmFwaCBhcmUgb2J2aW91cy4gV2UgY2FuIHNlZSB0aGF0IERvbmFsZCBUcnVtcCBoYXMgdGhlIGhpZ2hlc3Qgc2NvcmUgdmFsdWUgaW4gaGlzIGluYXVndXJhdGlvbiBzcGVlY2hlcy4gV2hpbGUgaW4gbm9taW5lZSBhbmQgcHVibGljIHNwZWVjaGVzLCB0aGUgc2NvcmVzIGFyZSBtdWNoIGxvd2VyLCB3aGljaCBtYXkgc3VnZ2VzdCB0aGF0IGhlIGlzIGEgIm91dHJpZ2h0IiBndXkgd2hvIHdvdWxkIG5vdCBjb250cm9sIGhpcyB3b3JkIGV2ZW4gaW4gcHVibGljLgoKKipzZW50aW1lbnQgYnkgc2VudGVuY2UqKgoKTm93IHdlIGdvIG9uZSBzdGVwIGZ1cnRoZXIgdG8gYW5hbHl6ZSBoaXMgc3BlZWNoZXMuIFRoaXMgdGltZSB3ZSB3aWxsIGFuYWx5emUgaGlzIHNlbnRpbWVudHMgYnkgc2VudGVuY2UuIFdlIHdpbGwgY2FsY3VsdGUgdGhlIHNjb3JlIG9mIGVhY2ggc2VudGVuY2UuIEFsc28sIHdlIHdpbGwgc2VlIHdoYXQgZXhhY3RseSBhcmUgdGhlIG1vc3QgcG9zaXRpdmUgKG5lZ2F0aXZlKSBzZW50ZW5jZXMgaGUgc2FpZC4gQW5kIHdlIHdpbGwgY29tcGFyZSB0aGVtIHdpdGggdGhvc2Ugb2NjdXIgaW4gYW5vdGhlciBub21pbmVlJ3Mgc3BlZWNoZXMsIEhpbGxhcnkgQ2xpbnRvbi4KCkRvbmFsZCBUcnVtcCdzIG1vc3QgcG9zaXRpdmUgc2VudGVuY2VzOgpgYGB7cixlY2hvPUZBTFNFfQpyZXN1bHRfcG9zIDwtIHNlbnRlbmNlLmxpc3QgJT4lCiAgICAgICAgICBtdXRhdGUoc2NvcmUgPSAocG9zaXRpdmUgLSBuZWdhdGl2ZSkgLyAocG9zaXRpdmUgKyBuZWdhdGl2ZSkpICU+JQogICAgICAgICAgZmlsdGVyKEZpbGUgPT0gIkRvbmFsZEpUcnVtcCIsIHR5cGUgPT0gImluYXVnIiwgc2NvcmUgPT0gMSwgc2VudGVuY2VzICE9ICIiKQpoZWFkKHJlc3VsdF9wb3Mkc2VudGVuY2VzLDUpCmBgYAoKRG9uYWxkIFRydW1wJ3MgbW9zdCBuZWd0aXZlIHNlbnRlbmNlczoKYGBge3IsZWNobz1GQUxTRX0KcmVzdWx0X25hZyA8LSBzZW50ZW5jZS5saXN0ICU+JQogICAgICAgICAgbXV0YXRlKHNjb3JlID0gKHBvc2l0aXZlIC0gbmVnYXRpdmUpIC8gKHBvc2l0aXZlICsgbmVnYXRpdmUpKSAlPiUKICAgICAgICAgIGZpbHRlcihGaWxlID09ICJEb25hbGRKVHJ1bXAiLCB0eXBlID09ICJzcGVlY2hlcyIsIHNjb3JlID09IC0xLCBzZW50ZW5jZXMgIT0gIiIpCnJlc3VsdF9uYWckc2VudGVuY2VzWzI6Nl0KYGBgCgpIaWxsYXJ5IENsaW50b24ncyBtb3N0IHBvc2l0aXZlIHNlbnRlbmNlczoKYGBge3IsZWNobz1GQUxTRX0Kc2VudGltZW50X21lc3NhZ2VzIDwtIHNlbnRlbmNlLmxpc3QgJT4lCiAgZmlsdGVyKHR5cGUgPT0gImluYXVnIiwgRmlsZSA9PSAiRG9uYWxkSlRydW1wIikgJT4lCiAgbXV0YXRlKHNjb3JlID0gKHBvc2l0aXZlIC0gbmVnYXRpdmUpIC8gKHBvc2l0aXZlICsgbmVnYXRpdmUpKSAlPiUKICBhcnJhbmdlKGRlc2Moc2NvcmUpKQoKcmVzdWx0X3BvcyA8LSBzZW50ZW5jZS5saXN0ICU+JQogICAgICAgICAgbXV0YXRlKHNjb3JlID0gKHBvc2l0aXZlIC0gbmVnYXRpdmUpIC8gKHBvc2l0aXZlICsgbmVnYXRpdmUpKSAlPiUKICAgICAgICAgIGZpbHRlcihGaWxlID09ICJIaWxsYXJ5Q2xpbnRvbiIsIHNjb3JlID09IDEsIHNlbnRlbmNlcyAhPSAiIikKaGVhZChyZXN1bHRfcG9zJHNlbnRlbmNlcyw1KQpgYGAKCkhpbGxhcnkgQ2xpbnRvbidzIG1vc3QgbmVnYXRpdmUgc2VudGVuY2VzOgpgYGB7cixlY2hvPUZBTFNFfQpyZXN1bHRfbmFnIDwtIHNlbnRlbmNlLmxpc3QgJT4lCiAgICAgICAgICBtdXRhdGUoc2NvcmUgPSAocG9zaXRpdmUgLSBuZWdhdGl2ZSkgLyAocG9zaXRpdmUgKyBuZWdhdGl2ZSkpICU+JQogICAgICAgICAgZmlsdGVyKEZpbGUgPT0gIkhpbGxhcnlDbGludG9uIiwgdHlwZSA9PSAibm9taW4iLCBzY29yZSA9PSAtMSwgc2VudGVuY2VzICE9ICIiKQoocmVzdWx0X25hZyRzZW50ZW5jZXMpW2MoNyw5LDEyLDE3LDIwKV0KYGBgCgpGcm9tIHRoZSBhYm92ZSBhbmFseXNpcywgd2UgY2FuIHNlZSBzb21lIGludGVyZXN0aW5nIHBhdHRlcm5zLiBCYXNlZCBvbiBzb21lIG9mIHRoZSBtb3N0IHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBzZW50ZW5jZXMsIHdlIGNhbiBzZWUgdGhhdCBEb25hbGQgVHJ1bXAgaXMgYW4gIm91dHJpZ2h0IiBvciBldmVuICJleHRyZW1lIiBub21pbmVlLiBXZSBjYW4gc2VlIHRoYXQgc29tZSBvZiBoaXMgYmFkIHdvcmRzIGRpcmVjdGx5IGFpbSBhdCBzb21lb25lIG9yIHNvbWV0aGluZy4gSGUga2luZCBvZiBjYW5ub3QgY29udHJvbCBoaW1zZWxmIHNheWluZyB0aGVtLiBPbiB0aGUgb3RoZXIgaGFuZCwgZm9yIGFub3RoZXIgbm9taWVlIGluIHRoaXMgeWVhciwgSGlsbGFyeSBDbGludG9uLCBldmVuIGhlciB0b3AgbmVnYXRpdmUgd29yZHMgYXJlIG1vcmUgb2YgbGlrZSBzdGF0aW5nIHNvbWUgZmFjdHMgcmF0aGVyIHRoYW4gZXhwbGljaXRseSBhaW1pbmcgYXQgc29tZW9uZS4KCgoKCg==